package org.example.oop.thread;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * org.example.oop.thread
 *
 * @author moLei
 * @description todo 实现备忘录功能，增加导入导出功能
 *              1.增加菜单，菜单中显示导出，导入功能
 *              2.导出：将所有日记文件打包压缩
 *              3.导入：将压缩包解压，获取数据展示
 * @date 2025/6/25
 */
@Slf4j
public class MemoExercises {

    /**
     * 控制变量
     */
    public static File currentFile;
    public static Boolean index = true;
    public static String zipName = "memo.zip";
    /**
     * 备忘录文件夹
     */
    private static final String MEMO_DIR = "memo";

    public static void main(String[] args) {
        // memo();
        // toZip(new File(MEMO_DIR));
        unZip();
    }

    /**
     * 解压缩备忘录
     */
    public static void unZip() {
        // 获取压缩包文件
        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipName))) {
            ZipEntry zipEntry;
            while ((zipEntry = zis.getNextEntry()) != null) {
                File file = new File(zipEntry.getName());
                // 如果压缩时使用了File.separator那么在解压时windows系统就无法使用这个zipEntry.isDirectory()方法进行快捷判断，得自己手动判断
                if (zipEntry.getName().endsWith(File.separator) || zipEntry.isDirectory()) {
                    file.mkdirs();
                } else {
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(zipEntry.getName()));
                    int len;
                    byte[] buffer = new byte[1024];
                    while ((len = zis.read(buffer)) != -1) {
                        bos.write(buffer, 0, len);
                    }
                    bos.close();
                }
            }
        } catch (Exception e) {
            log.error("解压缩异常：{}", e.getMessage(), e);
        }
    }

    /**
     * 压缩备忘录
     */
    public static void toZip(File file) {
        try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipName))) {
            toZipRecursion(out, file, file.getName());
        } catch (Exception e) {
        }
    }

    public static void toZipRecursion(ZipOutputStream out, File file, String dir) throws IOException {
        if (file.isFile()) {
            ZipEntry entry = new ZipEntry(dir + File.separator + file.getName());
            out.putNextEntry(entry);
            // 写入数据
            try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
                byte[] buf = new byte[1024];
                int len;
                while ((len = bis.read(buf)) != -1) {
                    out.write(buf, 0, len);
                }
                out.closeEntry();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            ZipEntry entry = new ZipEntry(dir + File.separator + file.getName() + File.separator);
            out.putNextEntry(entry);
            out.closeEntry();
            for (File listFile : file.listFiles()) {
                toZipRecursion(out, listFile, entry.getName());
            }
        }
    }

    /**
     * 备忘录功能
     */
    private static void memo() {
        // 获取文件夹
        File dir = new File(MEMO_DIR);
        // 文件夹不存在，创建文件夹
        if (!dir.exists()) {
            dir.mkdirs();
        }
        // 获取当前文件夹
        currentFile = new File(MEMO_DIR);
        // 获取备忘录文件名
        Scanner scan = new Scanner(System.in);
        String next = null;
        // 文件名映射集合
        Map<String, File> fileMapper = new HashMap<>();
        while (index) {
            // 打印控制台信息
            printConsole(fileMapper);
            next = scan.nextLine();
            // 校验输入的字符是否符合规则
            Pattern pattern = Pattern.compile("^[1-9][0-9]*$|#|d");
            Matcher matcher = pattern.matcher(next);
            if (!matcher.matches()) {
                // 清空控制台信息
                clearScreen();
                System.out.println("校验失败，请重新输入！");
            } else {
                // 控制跳出循环，进行下一步
                index = false;
            }
            // 进行文件的编辑
            editFile(next, fileMapper, scan);
        }
    }


    /**
     * 编辑文件
     * @param next 用户输入的选择项
     * @param fileMapper 文件映射
     * @return
     */
    private static void editFile(String next, Map<String, File> fileMapper, Scanner scan) {
        System.out.println("请输入exit(0)进行退出！！！");
        // 判断是读取已有文件还是新建文件进行编辑
        if (next.equals("#")) {
            System.out.println("输入备忘录文件名：");
            String fileName = scan.nextLine();
            // 新建文件
            File file = new File(currentFile, fileName);
            // 创建文件
            // 输入数据
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, true))) {
                String line;
                while (scan.hasNextLine()) {
                    line = scan.nextLine();
                    if (line.equals("exit(0)")) {
                        index = false;
                        break;
                    }
                    writer.write(line);
                    writer.newLine();
                }
            } catch (Exception e) {
                index = true;
                log.error("文件写入异常：{}", e.getMessage(), e);
            }
        } else if (next.equals("d")) {
            // 创建文件夹
            System.out.println("输入文件夹名称：");
            String dirName = scan.nextLine();
            File dir = new File(currentFile, dirName);
            dir.mkdirs();
            currentFile = dir;
            index = true;
        } else if (next.equals("exit(0)")) {

        } else {
            // 在已有文件中进行编辑
            // 获取选中的中间
            File file = fileMapper.get(next);
            // 判断是文件夹还是文件
            if (file.isDirectory()) {
                // 进入子文件夹
                clearScreen();
                currentFile = file;
                index = true;
                return;
            }

            // 判断文件是否存在
            if (file == null || !file.exists() || !file.isFile()) {
                // 文件不存在
                clearScreen();
                System.out.println("文件不存在！");
                // 继续进行循环打印
                index = true;
            }
            // 文件存在，对文件进行操作
            // 打印文件内容
            try (BufferedReader reader = new BufferedReader(new FileReader(file));
                 BufferedWriter writer = new BufferedWriter(new FileWriter(file, true))) {
                // 读取文件内容，打印到控制台
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
                // 进行文件的续写
                while (scan.hasNextLine()) {
                    line = scan.nextLine();
                    if (line.equals("exit(0)")) {
                        index = false;
                        break;
                    }

                    writer.write(line);
                    // 需要手动换行
                    writer.newLine();
                }
            } catch (Exception e) {
                index = true;
                log.error("文件编辑异常：{}", e.getMessage(), e);
            }
        }
    }

    /**
     * 清空控制台
     */
    public static void clearScreen() {
        try {
            // 判断系统是windows还是linux
            if (System.getProperty("os.name").toLowerCase().contains("win")) {
                new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
            } else {
                new ProcessBuilder("clear").inheritIO().start().waitFor();
            }
        } catch (Exception e) {
            log.error("清空控制台失败：{}", e.getMessage(), e);
        }
    }

    /**
     * 打印信息
     */
    public static void printConsole(Map<String, File> fileMapper) {
        System.out.println(String.format("目录【%s】下有以下文件，请输入序号选择已有文件进行编辑，或输入#号键按回车进行新建文件，输入d进行新建文件夹：", currentFile.getPath()));
        // 获取当前文件夹下有那些文件
        updateFileMapper(fileMapper);
        // 打印文件列表
        for (int i = 1; i <= fileMapper.size(); i++) {
            System.out.println(String.format("%d: %s", i, fileMapper.get(i + "").getName()));
        }
        System.out.println("请输入你的选择：");
    }

    /**
     * 根据当前文件更新文件映射集合
     */
    public static void updateFileMapper(Map<String, File> fileMapper) {
        // 更新前需要清除原有的数据
        fileMapper.clear();
        for (int i = 0; i < currentFile.listFiles().length; i++) {
            fileMapper.put(i + 1 + "", currentFile.listFiles()[i]);
        }
    }
}
